﻿using System;
using System.Xml;
using Notoric.Model.Internal;
using Notoric.Model.Packaging;

namespace Notoric.Model.Elements
{
    /// <summary>
    /// Represents a textual section.
    /// </summary>
    public class TextSectionElement : SectionElement
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="TextSectionElement"/> class.
        /// </summary>
        /// <param name="packagePart">
        /// <para>
        /// Type: <see cref="PagePart"/>
        /// </para>
        /// <para>
        /// The page part that owns this section.
        /// </para>
        /// </param>
        /// <param name="owner">
        /// <para>
        /// Type: <see cref="PageElement"/>
        /// </para>
        /// <para>
        /// The page that directly owns this section.
        /// </para>
        /// </param>
        /// <param name="interiorCreator">
        /// <para>
        /// Type: <see cref="SectionInteriorCreator"/>
        /// </para>
        /// <para>
        /// The method that will create the interior of the section.
        /// </para>
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Any of the arguments is <see langword="null"/>.
        /// </exception>
        public TextSectionElement(PagePart packagePart, PageElement owner, SectionInteriorCreator interiorCreator)
            : base(packagePart, owner, interiorCreator)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TextSectionElement"/> class.
        /// </summary>
        /// <param name="packagePart">
        /// <para>
        /// Type: <see cref="XmlPackagePart"/>
        /// </para>
        /// <para>
        /// The package part that owns this element.
        /// </para>
        /// </param>
        /// <param name="owner">
        /// <para>
        /// Type: <see cref="ModelElement"/>
        /// </para>
        /// <para>
        /// The page element that directly owns this section.
        /// </para>
        /// </param>
        /// <param name="element">
        /// <para>
        /// Type: <see cref="XmlElement"/>
        /// </para>
        /// <para>
        /// An XML element that represents this object.
        /// </para>
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="packagePart"/> or <paramref name="element"/> is <see langword="null"/>.
        /// </exception>
        public TextSectionElement(XmlPackagePart packagePart, ModelElement owner, XmlElement element)
            : base(packagePart, owner, element)
        {
            Interior = ModelElement.LoadElement<SectionInteriorElement>(packagePart, this, (XmlElement)InteriorElement.FirstChild);
        }

        #endregion
        
        #region SectionElement Members

        /// <inheritdoc/>
        protected override XmlElement CreateObjectElementCore(XmlDocument document)
        {
            var element = document.CreateElement(
                PackageVocabulary.PackageNamespacePrefix,
                PackageVocabulary.TextSectionElementName,
                PackageVocabulary.PackageNamespaceUri
                );

            return element;
        }

        /// <inheritdoc/>
        internal override bool HandleBorderRequest(Internal.SectionBorderRequest request)
        {
            if (request is Internal.TextSectionBorderRequest)
                return Interior.HandleBorderRequest(request);

            return false;
        }

        #endregion
    }

    /// <summary>
    /// Stores the data of a <see cref="TextSectionElement"/> in the Rich Text Format.
    /// </summary>
    public class RtfTextSectionInteriorElement : SectionInteriorElement
    {
        #region Constructors

        /// <summary>
        /// Creates a new <see cref="RtfTextSectionInteriorElement"/> instance.
        /// </summary>
        /// <param name="packagePart">
        /// <para>
        /// Type: <see cref="XmlPackagePart"/>
        /// </para>
        /// <para>
        /// The package part that owns this element.
        /// </para>
        /// </param>
        /// <param name="owner">
        /// <para>
        /// Type: <see cref="TextSectionElement"/>
        /// </para>
        /// <para>
        /// The text section element that directly owns this interior.
        /// </para>
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="packagePart"/> or <paramref name="owner"/> is <see langword="null"/>.
        /// </exception>
        internal RtfTextSectionInteriorElement(XmlPackagePart packagePart, TextSectionElement owner)
            : base(packagePart, owner)
        {
            content.AppendData(@"{\rtf1\ansi\ansicpg1250\deff0\deflang1029{\fonttbl{\f0\fnil\fcharset0 Calibri;}}");
        }

        /// <summary>
        /// Creates a new <see cref="RtfTextSectionInteriorElement"/> instance.
        /// </summary>
        /// <param name="packagePart">
        /// <para>
        /// Type: <see cref="XmlPackagePart"/>
        /// </para>
        /// <para>
        /// The package part that owns this element.
        /// </para>
        /// </param>
        /// <param name="owner">
        /// <para>
        /// Type: <see cref="ModelElement"/>
        /// </para>
        /// <para>
        /// The element that directly owns this interior.
        /// </para>
        /// </param>
        /// <param name="element">
        /// <para>
        /// Type: <see cref="XmlElement"/>
        /// </para>
        /// <para>
        /// An XML element that represents this object.
        /// </para>
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="packagePart"/>, <paramref name="owner"/> or <paramref name="element"/> is <see langword="null"/>.
        /// </exception>
        internal RtfTextSectionInteriorElement(XmlPackagePart packagePart, ModelElement owner, XmlElement element)
            : base(packagePart, owner, element)
        {
            content = (XmlCDataSection)element.FirstChild;
        }

        #endregion

        #region SectionInteriorElement Members

        /// <inheritdoc/>
        protected override XmlElement CreateObjectElementCore(XmlDocument document)
        {
            var element = document.CreateElement(
                PackageVocabulary.PackageNamespacePrefix,
                PackageVocabulary.RtfTextSectionInteriorElementName,
                PackageVocabulary.PackageNamespaceUri
                );

            content = document.CreateCDataSection("");
            element.AppendChild(content);

            return element;
        }

        /// <inheritdoc/>
        protected override void CreateContentCore(object parameter)
        {
            
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the serialized RTF content.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="string"/>
        /// </para>
        /// <para>
        /// The content in its serialized version (in Rich Text Format).
        /// </para>
        /// </value>
        public string RtfContent
        {
            get { return content.Data; }
            set 
            { 
                content.ReplaceData(0, content.Length, value);

                RaisePropertyChanged("RtfContent");
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Creates a new interior instance.
        /// </summary>
        /// <param name="packagePart">
        /// <para>
        /// Type: <see cref="XmlPackagePart"/>
        /// </para>
        /// <para>
        /// The package part that will own the interior.
        /// </para>
        /// </param>
        /// <param name="owner">
        /// <para>
        /// Type: <see cref="SectionElement"/>
        /// </para>
        /// <para>
        /// The text section that will directly own the interior.
        /// </para>
        /// </param>
        /// <returns>
        /// <para>
        /// Type: <see cref="SectionInteriorElement"/>
        /// </para>
        /// <para>
        /// The created section interior instance.
        /// </para>
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// Any of the arguments is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The <paramref name="owner"/> is not a <see cref="TextSectionElement"/>.
        /// </exception>
        public static SectionInteriorElement Create(XmlPackagePart packagePart, SectionElement owner)
        {
            if (owner is TextSectionElement)
                return new RtfTextSectionInteriorElement(packagePart, owner as TextSectionElement);
            else
                throw new ArgumentException("The owner has to be a TextSectionElement!", "owner");
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Holds the RTF content.
        /// </summary>
        private XmlCDataSection content;

        #endregion
    }
}
